@use "../core/color";
@use "../core/layout";
@use "../core/typography";

// Form input fields
// -----------------
// Specs: https://goo.gl/pEV9E1

@at-root {
  // Padding between top border of input and input text. This includes space
  // for the field label
  $top-padding: 35px;
  $top-padding-no-label: 5px;

  // Padding between bottom border of input and input text.
  $bottom-padding: 15px;
  $bottom-padding-no-label: 5px;

  // Horizontal padding between focus ring and input field / validation messages
  $h-padding: 10px;
  // Max width of validation error messages when shown to the right of the
  // input field
  $validation-message-width: 200px;

  .form-input {
    // Margin between input fields
    margin-bottom: 15px;
    position: relative;

    background-color: color.$white;
  }

  .form-input.is-editing {
    z-index: layout.$zindex-modal-content;
  }

  .form-input.is-hidden {
    display: none;
  }

  .form-input.is-error {
    & > .form-input__label {
      color: color.$brand;
    }

    & > .form-input__input {
      color: color.$brand;
    }

    & > .form-input__error-list {
      display: list-item;
    }
  }

  // Descriptive label above the input field
  .form-input__label {
    @include typography.font-normal;

    position: absolute;
    top: 10px;
    left: $h-padding;

    color: color.$grey-5;

    display: flex;
    // The label is a sibling of the <input> field. Raise it above the <input>
    // so that the field's tooltip appears above the focus ring
    z-index: 1;
  }

  .form-input__character-counter {
    @include typography.font-normal;

    // Show fallback "counter" if loading js times out.
    .env-js-timeout & {
      display: block;
    }

    // Immediately hide counter if js capable - prevents momentary flash of
    // unenhanced fallback counter before js kicks in.
    .env-js-capable & {
      display: none;
    }

    // The js controller adds this class when it's ready - show the now
    // enhanced counter.
    &.is-ready {
      display: block;
    }

    &.is-too-long {
      color: color.$brand;
      font-weight: bold;
    }

    position: absolute;
    bottom: 10px;
    right: $h-padding;

    color: color.$grey-5;
  }

  .form-input__required {
    color: color.$brand;
  }

  .form-input__hint-icon {
    display: none;
    margin-left: 6px;
    margin-top: 1px;
    position: relative;

    .env-js-capable & {
      display: block;
    }

    .env-js-timeout & {
      display: none;
    }
  }

  .form-input__hint {
    @include typography.font-normal;

    color: color.$grey-5;
    margin-top: -10px;

    .env-js-capable & {
      display: none;
    }

    .env-js-timeout & {
      display: block;
    }
  }

  // The actual <input> element for the field
  .form-input__input {
    padding-left: $h-padding;
    padding-right: $h-padding;
    width: 100%;

    background: none;
    color: color.$grey-6;
    font-size: typography.$input-font-size;
    outline: none;
    border: 1px solid color.$grey-3;
    border-radius: 3px;
  }

  // Set the padding depending on whether or not this field has an associated
  // label. The `<label>` lives outside the input in the DOM but is positioned
  // _inside_ the `<input>`'s border visually.
  //
  // We do this rather than use a separate element for the field's border so
  // that clicking anywhere inside the visual border focuses the input.
  .form-input__input.has-label {
    padding-top: $top-padding;
    padding-bottom: $bottom-padding;
    --bottom-padding: #{$bottom-padding};
  }

  .form-input__input:not(.has-label) {
    padding-top: $top-padding-no-label;
    padding-bottom: $bottom-padding-no-label;
    --bottom-padding: #{$bottom-padding-no-label};
  }

  select.form-input__input {
    margin-top: $top-padding;
  }

  .form-input__input.has-hint {
    .env-js-capable & {
      padding-top: $top-padding;
    }
  }

  .form-input__input:hover {
    border: 1px solid color.$grey-4;
  }

  // Thicker border used when input field has focus or has a validation error
  @mixin thick-border {
    // Adjust position of <input> to keep input field content at the same
    // position, given the thicker border. We adjust the position rather than
    // the padding because there are other states (eg. whether the form field
    // has a hint) that affect the amount of padding required and this avoids
    // doubling the number of those states.
    position: relative;
    left: -1px;
    top: -1px;

    // Assume largest possible padding if CSS vars are not supported.
    padding-bottom: $bottom-padding - 2px;
    padding-bottom: calc(var(--bottom-padding) - 2px);

    border-width: 2px;
  }

  // Show a thick border around focused input fields. When inline editing is
  // enabled, we may also show the field as focused if its Save/Cancel buttons
  // are focused but the <input> itself is not
  .form-input__input:focus,
  .form-input.is-focused > .form-input__input {
    @include thick-border;
    border-color: color.$grey-6;
  }

  .form-input.is-error > .form-input__input {
    @include thick-border;
    border-color: color.$brand;
    padding-right: $validation-message-width + 10px;
  }

  .form-input__input:invalid {
    // Disable default glow for invalid input fields in Firefox.
    // See https://hyp.is/Z3bV7FV8EeaKSc_QAoTqRw
    box-shadow: none;
  }

  // Validation error messages
  .form-input__error-list {
    // The error list is only shown when the input is in an `error` state
    display: none;
  }

  .form-input__error-item {
    max-width: $validation-message-width;
    position: absolute;
    right: $h-padding;
    top: $h-padding;

    color: color.$brand;
  }

  @include layout.touch-input {
    .form-input__input {
      font-size: typography.$touch-input-font-size;
    }
  }

  // On narrow screens, display validation error messages underneath the
  // input field.
  @media screen and (max-width: layout.$max-phone-width) {
    .form-input.is-error > .form-input__input {
      padding-bottom: $bottom-padding + 25px;
      padding-right: $h-padding - 1px;
    }

    .form-input__error-item {
      top: unset;
      bottom: 10px;
      left: $h-padding;
      right: $h-padding;
      max-width: unset;
    }
  }
}
